import { MatchInfo } from 'src/modules/match/entities/match.entity';
import { Group } from 'src/modules/group/entities/group.entity';
import { EventToPlayer } from 'src/modules/event-to-player/entities/event-to-player.entity';
import { getE2PCount } from 'src/common/utils/matchUtils';
import { assign } from 'lodash';
import {
  EventTypeEnum,
  MatchPlayerStatusEnum,
  registrationIndexInitValue,
} from 'src/common/constant/enums';
import { HttpException, HttpStatus } from '@nestjs/common';
import { Stage } from 'src/modules/stage/entities/stage.entity';

// 帮我用js实现一下这个需求：
// 1. 目标是实现羽毛球赛循环赛的比赛生成功能
// 2. 入参1: totalPlayers:Array<number>, 所有参赛人员的编号
// 3. 入参2: direction，循环方向，1为正向，-1 为逆向
// 4. otherMatchParam, 作为返回数组元素的模版
// 5. otherMatchParam.homePlayer 和 otherMatchParam.awayPlayer 用作表示比赛双方运动员的编号
// 6. otherMatchParam.groupLoopIndex 用作比赛的轮次

const createSubMatchE2P = (
  parentMatchE2P: EventToPlayer,
  subTeamMatchType: EventTypeEnum,
  registrationIndex: string,
  isByePlayer?,
) => {
  const { stageOrderInEvent, eventId } = parentMatchE2P;
  const e2p = new EventToPlayer();
  e2p.registrationIndex = registrationIndex; //`${i}-${index + 1}`;
  e2p.eventId = eventId;
  e2p.subTeamMatchType = subTeamMatchType;
  e2p.stageOrderInEvent = stageOrderInEvent;
  if (isByePlayer) {
    e2p.player1Name = '轮空';
    e2p.isByePlayer = true;
  }
  return e2p;
};

function createRound(
  totalPlayers: EventToPlayer[],
  direction,
  otherMatchParam: Partial<MatchInfo>,
): Array<MatchInfo> {
  const numPlayers = totalPlayers.length;
  const matches: MatchInfo[] = [];

  // 处理参赛人数为奇数的情况，添加一个虚拟选手
  const players = [...totalPlayers];
  if (numPlayers % 2 === 1) {
    players.push(null);
  }

  const numRounds = players.length - 1;

  for (let round = 0; round < numRounds; round++) {
    const roundMatches = [];
    for (let i = 0; i < players.length / 2; i++) {
      const homePlayer = players[i];
      const awayPlayer = players[players.length - 1 - i];

      // 排除虚拟选手的比赛
      if (homePlayer !== null && awayPlayer !== null) {
        // homePlayer = e2pMap[homePlayerIndex] createE2P(homePlayerIndex);
        const match = {
          ...otherMatchParam,
          homePlayer: homePlayer,
          awayPlayer: awayPlayer,
          groupLoopIndex: round + 1,
        };
        roundMatches.push(match);
      }
    }
    matches.push(...roundMatches);

    // 根据循环方向旋转数组
    if (direction === 1) {
      // 正向循环
      const temp = players[players.length - 1];
      for (let i = players.length - 1; i > 1; i--) {
        players[i] = players[i - 1];
      }
      players[1] = temp;
    } else if (direction === -1) {
      // 逆向循环
      const temp = players[1];
      for (let i = 1; i < players.length - 1; i++) {
        players[i] = players[i + 1];
      }
      players[players.length - 1] = temp;
    }
  }

  return matches;
}
export const genTeamSubMatches = (
  match: MatchInfo,
  stageInfo: Stage,
  totalPlayers: EventToPlayer[],
  matchTemplate: Partial<MatchInfo>,
) => {
  // 生成子比赛
  const { gameRuleId, rallyRuleId, mustCheckIn } = stageInfo;
  const totalPlayerMap = totalPlayers.reduce((acc, cur) => {
    acc[cur.registrationIndex] = cur;
    return acc;
  }, {});
  if (!stageInfo.stageEvents || !stageInfo.stageEvents.length) {
    throw new HttpException(
      'stageEvents is empty',
      HttpStatus.INTERNAL_SERVER_ERROR,
    );
  }
  const subTeamMatchLength = stageInfo.stageEvents.length;
  match.subMatchInfos = [];
  for (let i = 0; i < subTeamMatchLength; i++) {
    const {
      homePlayer,
      awayPlayer,
      groupLoopIndex,
      createBy,
      updateBy,
      isTeamMatch,
    } = match;
    const subTeamMatch = assign(new MatchInfo(), matchTemplate);
    const subTeamMatchOrder = stageInfo.stageEvents[i].eventOrder;
    subTeamMatch.type = stageInfo.stageEvents[i].type;
    if (homePlayer && awayPlayer) {
      // 针对淘汰赛的非第一轮，没有比赛选手，所以不生成选手信息
      // subTeamMatch.homePlayer =
      //   totalPlayerMap[`${homePlayer.registrationIndex}-${subTeamMatchOrder}`];
      // subTeamMatch.awayPlayer =
      //   totalPlayerMap[`${awayPlayer.registrationIndex}-${subTeamMatchOrder}`];
      subTeamMatch.homePlayer = createSubMatchE2P(
        totalPlayerMap[`${homePlayer.registrationIndex}`],
        subTeamMatch.type,
        `${homePlayer.registrationIndex}-${subTeamMatchOrder}`,
      );
      subTeamMatch.awayPlayer = createSubMatchE2P(
        totalPlayerMap[`${homePlayer.registrationIndex}`],
        subTeamMatch.type,
        `${awayPlayer.registrationIndex}-${subTeamMatchOrder}`,
      );
    }
    subTeamMatch.subMatchOrder = subTeamMatchOrder;
    subTeamMatch.homePlayerRally = 0;
    subTeamMatch.awayPlayerRally = 0;
    subTeamMatch.groupLoopIndex = groupLoopIndex;
    subTeamMatch.isTeamMatch = isTeamMatch;
    subTeamMatch.createBy = createBy;
    subTeamMatch.updateBy = updateBy;
    subTeamMatch.rallyRuleId = rallyRuleId;
    subTeamMatch.gameRuleId = gameRuleId;
    match.subMatchInfos.push(subTeamMatch);
  }
};
export const handleRoundStage = (
  stageInfo: Stage,
  totalPlayers: Array<EventToPlayer>,
  isTeamEvent?: boolean,
) => {
  const {
    playerCount,
    gameRuleId,
    rallyRuleId,
    roundGroupCount,
    mustFinishMaxCountGame,
    mustFinishMaxCountMatch,
    mustCheckIn,
    tournamentId,
    categoryId,
    event,
    type: stageType,
    createBy,
    updateBy,
  } = stageInfo;
  // 先生成团队赛
  // const remainder = playerCount % roundGroupCount;
  const leastGroupPlayerCount = Math.floor(
    getE2PCount(stageType, playerCount, roundGroupCount) / roundGroupCount,
  );
  const totalPlayerMap = totalPlayers.reduce((acc, cur) => {
    acc[cur.registrationIndex] = cur;
    return acc;
  }, {});
  // let playerIndex = 0;
  // eslint-disable-next-line prettier/prettier
  const groupNameSuffix = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
  for (let i = 0; i < roundGroupCount; i++) {
    const playerGroup: EventToPlayer[] = [];
    const start = i * leastGroupPlayerCount;
    for (
      let playerIndex = start + registrationIndexInitValue;
      playerIndex <= start + leastGroupPlayerCount;
      playerIndex++
    ) {
      playerGroup.push(totalPlayerMap[`${playerIndex}`]);
    }
    // if (remainder && remainder > 0) {
    //   if (i < remainder) {
    //     playerGroup.push(totalPlayers[playerIndex++].registrationIndex);
    //   } else {
    //     // 补位
    //     playerGroup.push('byePlayer');
    //   }
    // }
    const matchTemplate = {
      type: event.type,
      // homePlayer: 1,
      // awayPlayer: 2,
      homePlayerRally: 0,
      awayPlayerRally: 0,
      homePlayerStatus: mustCheckIn
        ? MatchPlayerStatusEnum.NotCheckIn
        : MatchPlayerStatusEnum.CheckedIn,
      awayPlayerStatus: mustCheckIn
        ? MatchPlayerStatusEnum.NotCheckIn
        : MatchPlayerStatusEnum.CheckedIn,
      groupLoopIndex: i,
      isTeamMatch: isTeamEvent,
      createBy: createBy,
      updateBy: updateBy,
      gameRuleId,
      rallyRuleId,
      mustFinishMaxCountGame,
      mustFinishMaxCountMatch,
      tournamentId,
      categoryId,
      eventId: event.id,
    };
    const matchList = createRound(playerGroup, 1, matchTemplate);
    if (isTeamEvent) {
      matchList.forEach((v) => {
        genTeamSubMatches(v, stageInfo, totalPlayers, matchTemplate);
      });
    }
    const group = new Group();
    group.createBy = stageInfo.createBy;
    group.updateBy = stageInfo.updateBy;
    group.name = `${groupNameSuffix[i]} 组`;
    group.matchInfos = matchList;
    group.groupIndex = i;
    stageInfo.groups = stageInfo.groups || [];
    stageInfo.groups.push(group);
    console.log('entity.groups', stageInfo.groups.length);
  }
  return stageInfo;
  // return null;
};
export default createRound;
